//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>

//
// RamDisk
//
#define RAMDISK_SIZE    512

class RamDisk : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    virtual void Dispose();

public:
    byte_t  m_buffer[RAMDISK_SIZE];
};

ECode RamDisk::Read(
    /* [in] */ Int64 u64Offset,
    /* [in] */ Int32 bytesToRead,
    /* [out] */ MemoryBuf * pBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    if (pBuffer == NULL || !pBuffer->GetCapacity()
        || (int)bytesToRead > pBuffer->GetCapacity()
        || 0 == bytesToRead
        || RAMDISK_SIZE < u64Offset + bytesToRead) {
        return E_INVALID_ARGUMENT;
    }

    pBuffer->Copy((Byte *)&m_buffer[u64Offset], bytesToRead);

    if (NULL != ppCompletionEvent) *ppCompletionEvent = NULL;
    return NOERROR;
}

ECode RamDisk::Write(
    /* [in] */ Int64 u64Offset,
    /* [in] */ const MemoryBuf & buffer,
    /* [out] */ Int32 * pBytesWritten,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    if (buffer.IsNullOrEmpty()
        || RAMDISK_SIZE < u64Offset + buffer.GetUsed()
        || NULL == pBytesWritten) {
        return E_INVALID_ARGUMENT;
    }

    memcpy(m_buffer, buffer.GetPayload(), buffer.GetUsed());

    *pBytesWritten = buffer.GetUsed();

    if (NULL != ppCompletionEvent) *ppCompletionEvent = NULL;
    return NOERROR;
}

ECode RamDisk::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf & inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

void RamDisk::Dispose()
{
    delete this;
}

EXTERN IDeviceDriver * CDECL CreateRamDisk(uint_t uDeviceNo, void *pvParameter)
{
    RamDisk *pRamDisk = new RamDisk();
    if (NULL == pRamDisk) return NULL;

    pRamDisk->AddRef();
    return pRamDisk;
}
